package views;

import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.util.ArrayList;

import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.event.MouseInputListener;

import utils.ImageUtil;

import elements.Element;
import elements.Laser;
import elements.Light;
import elements.Stage;
import elements.TileMap;


public class GameView extends View{
	StageView stageView;
	MenuView menuView;
	public GameView(MainFrame mf,int width,int height){
		super(mf,width,height);
		this.setBackground(Color.black);
		stageView = new StageView(this);
		menuView = new MenuView(this);
		this.add(stageView);
		this.add(menuView);
	}
	class StageView extends JPanel implements MouseInputListener{
		GameView gameView;
		Stage stage;
		Cursor move = new Cursor(Cursor.MOVE_CURSOR);  // when element can only move
		Cursor rotate = new Cursor(Cursor.CROSSHAIR_CURSOR);// when element can only rotate
		Cursor normal = new Cursor(Cursor.HAND_CURSOR); //can both move and rotate
		boolean isSetted;
		boolean isEditmode ;
		String currentElement="";
		public StageView(GameView gameView){
			this.gameView = gameView;
			this.setBackground(Color.black);
			this.setPreferredSize(new Dimension(gameView.width,gameView.height-90));
			this.setFocusable(true);
			this.addMouseListener(this);
			this.addMouseMotionListener(this);
		    this.addMouseWheelListener(new MouseWheelListener() {
				@Override
				public void mouseWheelMoved(MouseWheelEvent arg0) {
					// TODO Auto-generated method stub
					int i = arg0.getWheelRotation();
					Light.size =Math.min(100, Math.max(1, Light.size+i*3));
					repaint();
				}
			});
			stage = new Stage();
		}
		
		public void paintComponent(Graphics g){
			super.paintComponent(g);
			Graphics2D g2 = (Graphics2D)g;
			if(!isSetted){
				//set the default context
				isSetted = true;
			}
			stage.draw(g2);
		}

		public Element detectElement(int x,int y){
				ArrayList<Element> laserList =stage.getLaserList(); 
				for(int i =0;i< laserList.size();i++){
					if(laserList.get(i).contains(x, y)){
						return laserList.get(i);
					}
				}
				ArrayList<Element> normalList =stage.getNormaList(); 
				for(int i =0;i< normalList.size();i++){
					if(normalList.get(i).contains(x, y)){
						return normalList.get(i);
					}
				}
				return null;
		}
		
		public void removeExist(Element existElement){
			stage.getElements()[existElement.getRindex()][existElement.getCindex()] = null;
			stage.getMap()[existElement.getRindex()][existElement.getCindex()] ="";
			ArrayList list =null;
			if(existElement.getType()==4){
				list = stage.getLaserList();
			}else if(existElement.getType()==5){
				list = stage.getCoinList();
			}else {
				list = stage.getNormaList();
			}
			for(int i =0;i<list.size();i++){
				if(existElement== list.get(i)){
					list.remove(i);return;
				}
			}
		}
		@Override
		public void mouseClicked(MouseEvent arg0) {
			// TODO Auto-generated method stub
			if(isEditmode && !"".equals(currentElement)){
				int mousex = arg0.getX();
				int mousey = arg0.getY();
				int[] index = TileMap.pixelToTile(mousex,mousey);
				Element existElement = stage.getElements()[index[0]][index[1]];
					if("R".equals(currentElement)){
						if(existElement!=null&&existElement.getType()!=1 &&existElement.getType()!=2&&existElement.getType()!=3)
							{	removeExist(existElement);
								stage.generateLight();
								this.repaint();
							}
					}else{
						if(existElement!=null&&existElement.getType()!=1 &&existElement.getType()!=2&&existElement.getType()!=3){
							removeExist(existElement);
							stage.createElement(index[0], index[1], currentElement);
							stage.generateLight();
							this.repaint();
						}else if(existElement==null){
						stage.createElement(index[0], index[1], currentElement);
						stage.generateLight();
						this.repaint();
						}
						
					}
				return;
			}
			
			
			if(SwingUtilities.isMiddleMouseButton(arg0)){
				Light.normal =! Light.normal;
				ImageUtil.currentStyle=(ImageUtil.currentStyle==2)?1:2;
				ImageUtil.imageCache.clear();
				stage.intiStage();
				this.repaint();
			}else{
				int mousex = arg0.getX();
				int mousey = arg0.getY();
				Element element =stage.getCurrentSelected();
				if(element!=null&&element.actType!=4&&element.actType!=2){
					if(SwingUtilities.isLeftMouseButton(arg0)){
						element.setDirection(element.getDirection()+1);
						String str = ""+element.getType()+"-"+element.getColor()+"-"+element.getDirection()+"-"+element.getActType();
						stage.getMap()[element.getRindex()][element.getCindex()]=str;
						stage.generateLight();
					}else {
						element.setDirection(element.getDirection()-1);
						String str = ""+element.getType()+"-"+element.getColor()+"-"+element.getDirection()+"-"+element.getActType();
						stage.getMap()[element.getRindex()][element.getCindex()]=str;
						stage.generateLight();
					}
					this.repaint();
				}
			}
			
		}

		@Override
		public void mouseEntered(MouseEvent arg0) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseExited(MouseEvent arg0) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mousePressed(MouseEvent arg0) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseReleased(MouseEvent arg0) {
			// TODO Auto-generated method stub
			if(isEditmode && !"".equals(currentElement)){return;}
			Element element = stage.getCurrentSelected();
			if(element!=null&&element.actType!=3&&element.actType!=4){
				int mousex = arg0.getX();
				int mousey = arg0.getY();
				int[] index = TileMap.pixelToTile(mousex,mousey);
				if("".equals(stage.getMap()[index[0]][index[1]])){
					stage.getMap()[element.getRindex()][element.getCindex()] = "";
					stage.getElements()[element.getRindex()][element.getCindex()] =null;
					element.setRindex(index[0]);
					element.setCindex(index[1]);
					String str = ""+element.getType()+"-"+element.getColor()+"-"+element.getDirection()+"-"+element.getActType();
					stage.getMap()[index[0]][index[1]]=str;
					stage.getElements()[index[0]][index[1]]=element;
				}else{
					element.setRindex(element.getRindex());
					element.setCindex(element.getCindex());
					stage.getMap()[element.getRindex()][element.getCindex()] =""+element.getType()+"-"+element.getColor()+"-"+element.getDirection()+"-"+element.getActType();
					stage.getElements()[element.getRindex()][element.getCindex()] =element;
				}
				if(element.getType()==Element.LASER)((Laser)(element)).show();
				stage.generateLight();
				this.repaint();
			}
		}

		@Override
		public void mouseDragged(MouseEvent arg0) {
			if(isEditmode && !"".equals(currentElement)){return;}
			// TODO Auto-generated method stub
			int mousex = arg0.getX();
			int mousey = arg0.getY();
			Element element = stage.getCurrentSelected();
			if(element!=null&&element.actType!=4&&element.actType!=3){
				stage.getMap()[element.getRindex()][element.getCindex()] = "";
				stage.getElements()[element.getRindex()][element.getCindex()] =null;
				element.setPosition(mousex,mousey);
				if(element.getType()==Element.LASER)((Laser)element).cancel();
				stage.generateLight();
				this.repaint();
			}
		}

		@Override
		public void mouseMoved(MouseEvent arg0) {
			// TODO Auto-generated method stub
			int mousex = arg0.getX();
			int mousey = arg0.getY();
			stage.setCurrentSelected( detectElement(mousex,mousey));
			if(stage.getCurrentSelected()!=null){
				this.setCursor(getCursorType(stage.getCurrentSelected().actType));
			}else{
				this.setCursor(Cursor.getDefaultCursor());
			}
		}
		
		public Cursor getCursorType(int i){
			Cursor cursor = null;
			switch (i) {
				case 1:	 cursor = normal;break;
				case 2:	 cursor = move;break;
				case 3:	 cursor = rotate;break;
			}
			return cursor;
		}
	}
	
	class MenuView extends JPanel{
		GameView gameView;
		ToolPanel toolPanel;
		EditPanel editPanel;
		public MenuView(GameView gameView){
			this.gameView = gameView;
			this.setPreferredSize(new Dimension(gameView.width-6,50));
			this.setFocusable(true);
			
			this.setLayout(new CardLayout());
			editPanel = new EditPanel(gameView);
			toolPanel = new ToolPanel(gameView);
			this.add("tool",toolPanel);
			this.add("edit",editPanel);
		}
		
	}
}
